from fastapi import APIRouter, Request, Form, Depends, HTTPException, Query
from fastapi.responses import JSONResponse, StreamingResponse
from sqlalchemy.orm import Session
from database import get_db
from models import Users, ApiCalls, ApiCallLogs
from datetime import datetime, date
import os
import json
import asyncio
import mimetypes
import requests
from parser import parse_video_share_url

router = APIRouter(tags=["视频解析模块"], prefix="/video")

LIMITS = {"free":5, "month":2000, "season":5000, "year":10000}


# 视频/图集解析接口
@router.post("/jiexi")
def jiexi(url: str = Form(...), request: Request = None, db: Session = Depends(get_db)):
    user_id = request.session.get("user_id")
    print("user_id = ", user_id)
    if not user_id:
        return JSONResponse({"code": 106, "msg": "请登录后使用"})

    # 1. 查询用户并检查是否存在
    user = db.query(Users).filter(Users.user_id == user_id).first()
    if not user:
        return JSONResponse({"code": 105, "msg": "用户不存在"})

    try:
        # 2. 检查账号状态（status=0）
        if user.status == 0:
            return JSONResponse({"code": 104, "msg": "账号错误，无法获取解析"})

        # 3. VIP状态检查逻辑
        current_time = datetime.utcnow()
        if user.vip_status != 0:
            # 若VIP有效但未设置过期时间，视为异常
            if not user.vip_expire:
                return JSONResponse({"code": 109, "msg": "VIP信息异常，请联系管理员"})

            # 检查是否过期
            if current_time > user.vip_expire:
                # 更新为非VIP状态
                user.vip_status = 0
                user.user_type = "free"
                db.commit()
                return JSONResponse({"code": 104, "msg": "无法获取解析（账号授权已过期）"})

        # 4. 检查接口权限（client_secret）
        client_id = user.client_id
        client_secret = user.client_secret
        if not client_secret:
            return JSONResponse({"code": 107, "msg": "请先开通接口权限"})

        # 5. 计算调用限制（limit）
        if user.user_type.value == 'admin':
            limit = 100000
        else:
            limit = LIMITS.get(user.user_type.value, 5)
        print("limit = ", limit, user.user_type.value)

        # 6. 检查当日调用次数（行锁防并发）
        today = date.today()
        # .with_for_update()  行锁（关键）
        record = db.query(ApiCalls).filter_by(user_id=user.user_id, call_date=today).with_for_update().first()

        if not record:
            record = ApiCalls(user_id=user.user_id, call_date=today, call_count=0)
            db.add(record)
            db.flush()  # 刷新以锁定行

        if record.call_count >= limit:
            db.rollback()
            return JSONResponse({"code": 108, "msg": "调用次数已达上限, 请升级套餐"})

        # 7. 执行解析并更新记录
        data = parse_video_or_images(url)
        record.call_count += 1
        log = ApiCallLogs(user_id=user.user_id, url=url)
        db.add(log)
        db.commit()  # 统一提交事务

        return JSONResponse({"code": 200, "msg": "解析成功", "data": data})
    except Exception as e:
        db.rollback()
        print(f"服务器内部错误{str(e)}")
        return JSONResponse({"code": 500, "msg": f"服务器内部错误{str(e)}"})
    finally:
        db.close()  # 确保关闭会话（可选，依赖框架配置）


# 解析函数
def parse_video_or_images(url: str) -> dict:
    try:
        # 根据分享链接解析
        video_parse_info = asyncio.run(parse_video_share_url(url))

        json_str_video_info = json.dumps(video_parse_info, ensure_ascii=False, indent=4, default=lambda x: x.__dict__)
        print(type(json_str_video_info), json_str_video_info)

        return json.loads(json_str_video_info)

    except Exception as e:
        # 记录解析失败的详细信息（可扩展日志）
        print(f"解析失败: {str(e)}")


# ✅ 新增：视频下载代理接口（解决 403 Forbidden）
@router.get("/download")
def download_video(url: str = Query(...), referer: str = Query(...)):
    headers = {
        "User-Agent": (
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
            "AppleWebKit/537.36 (KHTML, like Gecko) "
            "Chrome/114.0.0.0 Safari/537.36"
        ),
        "Referer": referer,
    }

    try:
        r = requests.get(url, headers=headers, stream=True, timeout=15)
        if r.status_code != 200:
            return JSONResponse({"code": r.status_code, "msg": "下载失败"})

        # 从 URL 提取文件名
        filename = os.path.basename(url.split("?")[0])
        if not filename or "." not in filename:
            # URL 没有扩展名，强制加后缀
            filename = "video.mp4"
        else:
            # 如果是视频流，也可以统一后缀
            ext = os.path.splitext(filename)[1].lower()
            if ext not in [".mp4", ".mov", ".mkv"]:
                filename += ".mp4"
        # if not filename:
        #     filename = "file"

        # 根据文件名获取 MIME 类型
        media_type, _ = mimetypes.guess_type(filename)
        if not media_type:
            media_type = "application/octet-stream"

        return StreamingResponse(
            r.iter_content(chunk_size=1024),
            media_type=media_type,
            headers={
                "Content-Disposition": f"attachment; filename={filename}"
            }
        )

    except Exception as e:
        raise HTTPException(status_code=500, detail=f"代理下载失败: {str(e)}")

